import React, { useState, useEffect } from 'react';
import type { NavigateFunction } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import {
  Alert,
  Avatar,
  Button,
  Divider,
  Dropdown,
  Image,
  Layout,
  Modal,
  Spin,
  Form,
  Checkbox,
  Input,
  InputNumber,
  Popover,
  Space,
  Switch,
  Upload,
  message,
  theme
} from 'antd';
import type { MenuProps } from 'antd';
import type { CheckboxChangeEvent } from 'antd/es/checkbox';
import type { UploadFile } from 'antd/es/upload/interface';
import {
  ContainerOutlined,
  ContainerTwoTone,
  InfoCircleOutlined,
  LogoutOutlined,
  KeyOutlined,
  ProfileOutlined,
  UploadOutlined
} from '@ant-design/icons';
import Cookies from 'js-cookie';
import userApi from '../api/userApi';
import { useStore, observer } from '../store/currentUser/storeHook';
import * as patterns from '../data/patterns';
import userImageData from '../data/userImageData';
import { userTypes, getOptionLabel } from '../data/statusData';

const { useToken } = theme;

const { Header } = Layout;

const HeaderLayout: React.FC = () => {
  const store: any = useStore();

  const [isUserModalOpen, setIsUserModalOpen] = useState(false);
  const [isUserDataLoading, setIsUserDataLoading] = useState(false);
  const [isUserFormSaving, setIsUserFormSaving] = useState(false);

  const [isPasswordModalOpen, setIsPasswordModalOpen] = useState(false);
  const [isPasswordFormSaving, setIsPasswordFormSaving] = useState(false);
  const [periodOfValidityDisabled, setPeriodOfValidityDisabled] = useState(false);

  const [isOpinionModalOpen, setIsOpinionModalOpen] = useState(false);

  const navigate: NavigateFunction = useNavigate();

  const [messageApi, contextHolder] = message.useMessage();
  const [userForm] = Form.useForm();
  const [passwordForm] = Form.useForm();
  const [opinionForm] = Form.useForm();
  const superuser: boolean = Form.useWatch('superuser', userForm);

  const [avatar, setAvatar] = useState<string | null>(null);
  const [avatarId, setAvatarId] = useState<string | null>(null);
  const [fileList, setFileList] = useState<UploadFile[]>([]);

  const xsrfToken: string = Cookies.get('XSRF-TOKEN') || 'XSRF-TOKEN';

  const { token } = useToken();
  const contentStyle: React.CSSProperties = {
    backgroundColor: token.colorBgElevated,
    borderRadius: token.borderRadiusLG,
    boxShadow: token.boxShadowSecondary,
  };
  const menuStyle: React.CSSProperties = {
    boxShadow: 'none',
  };

  const getMenuItems = () => {
    const menuItems: any[] = [
      {
        key: 'update_user_info',
        label: '用户信息',
        icon: <ProfileOutlined />
      },
      {
        key: 'change_password',
        label: '更改密码',
        icon: <KeyOutlined />
      },
      {
        key: 'logout',
        label: '退出登录',
        icon: <LogoutOutlined />
      }
    ];
    if (!store.currentUser.hasRole('admin')) {
      menuItems.splice(2, 0, {
        key: 'authorized_opinions',
        label: '审核意见',
        icon: store.currentUser.userData.authorizedOpinions ? <ContainerTwoTone /> : <ContainerOutlined />
      });
    }
    return menuItems;
  };

  const onUserMenuClick: MenuProps['onClick'] = (e) => {
    switch (e.key) {
      case 'update_user_info':
        setIsUserModalOpen(true);
        break;
      case 'change_password':
        setIsPasswordModalOpen(true)
        break;
      case 'authorized_opinions':
        setIsOpinionModalOpen(true);
        break;
      case 'logout':
        window.location.href = '/logout';
        break;
      default:
        break;
    }
  };

  const getUserInfo = (open: boolean) => {
    if (!open || isUserDataLoading) {
      return;
    }
    setIsUserDataLoading(true);
    store.currentUser.fetch();
    userApi.find(store.currentUser.userData.id).then((res: any) => {
      setIsUserDataLoading(false);
      if (res.success) {
        const userInfo = res.data;
        userInfo.avatarId = null;
        if (userInfo.avatar) {
          const avatar: string = userInfo.avatar.startsWith('/') ? userInfo.avatar : ('/' + userInfo.avatar);
          const list: UploadFile[] = [{
            uid: new Date().getTime() + '',
            name: 'avatar',
            status: 'done',
            url: avatar
          }];
          if (!(fileList.length === list.length && list.length === 1 && fileList[0].url === list[0].url)) {
            setFileList(list);
          }
        } else {
          if (!(fileList.length === 0)) {
            setFileList([]);
          }
        }
        userInfo.typeName = getOptionLabel(userTypes, userInfo.type);
        setAvatar(userInfo.avatar);
        setAvatarId(userInfo.avatarId);
        userForm.setFieldsValue(userInfo);
      } else {
        messageApi.error(res.message);
      }
    });
  };

  const updateUserInfo = (values: any) => {
    if (isUserFormSaving) {
      return;
    }
    setIsUserFormSaving(true);
    values.avatar = avatar;
    values.avatarId = avatarId;
    userApi.updateUserInfo(values).then((res: any) => {
      setIsUserFormSaving(false);
      if (res.success) {
        setIsUserModalOpen(false);
        const userData: any = { ...store.currentUser.userData };
        userData.avatar = res.data.avatar;
        store.currentUser.setUserData(userData);
        messageApi.info('用户信息修改成功')
      } else {
        messageApi.error(res.message);
      }
    });
  };

  const fillPasswordForm = (open: boolean) => {
    if (open) {
      passwordForm.setFieldsValue({
        oldPassword: '',
        newPassword: '',
        confirmPassword: '',
        periodOfValidity: {
          months: 1,
          neverExpire: false
        }
      });
      setPeriodOfValidityDisabled(false);
    }
  };

  const showOpinions = (open: boolean) => {
    if (open) {
      opinionForm.setFieldsValue({
        authorized: store.currentUser.hasRole('authorized'),
        authorizedOpinions: store.currentUser.userData.authorizedOpinions
      });
    }
  };

  const updateValidityStatus = (e: CheckboxChangeEvent) => {
    setPeriodOfValidityDisabled(e.target.checked);
    passwordForm.setFieldValue(['periodOfValidity', 'months'], e.target.checked ? null : 1);
  };

  const changePassword = (values: any) => {
    if (isPasswordFormSaving) {
      return;
    }
    values.periodOfValidity.months = values.periodOfValidity.months || 0;
    setIsPasswordFormSaving(true);
    userApi.changePassword(values).then((res: any) => {
      setIsPasswordFormSaving(false);
      if (res.success) {
        setIsPasswordModalOpen(false);
        store.currentUser.setNeedChangePassword(false);
        messageApi.info('密码修改成功');
      } else {
        messageApi.error(res.message);
      }
    });
  };

  useEffect(() => {
    store.currentUser.fetch();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  return (
    <>
      {contextHolder}
      <Header className="app-header">
        <div className="app-logo-container">
          <div
            className="app-logo"
            onClick={() => navigate('/')}
          >
            <Image
              src='/images/logo.png'
              preview={false}
              width={150}
            />
          </div>
        </div>
        <div className="app-user">
          <Dropdown
            arrow={true}
            menu={{
              items: getMenuItems(),
              onClick: onUserMenuClick
            }}
            trigger={['click']}
            popupRender={menu => (
              <div style={contentStyle}>
                <p className="username">
                  <span>
                    {store.currentUser.userData.username}
                  </span>
                  {
                    store.currentUser.userData.username ?
                      <small>
                        {
                          store.currentUser.hasRole('admin') ? '管理员' : (
                            store.currentUser.hasRole('authorized') ? '授权用户' : '未授权用户'
                          )
                        }
                      </small> :
                      null
                  }
                </p>
                <Divider style={{ margin: 0 }} />
                {React.cloneElement(menu as React.ReactElement, { style: menuStyle })}
              </div>
            )}
            overlayClassName="user-dropdown"
          >
            <Button
              type="link"
              style={{
                borderStyle: 'none',
                borderRadius: 0,
                height: 'auto',
                padding: 0
              }}
            >
              {
                store.currentUser.userData.avatar ?
                  <Avatar
                    draggable={false}
                    src={
                      <Image
                        src={store.currentUser.userData.avatar.startsWith('/') ? store.currentUser.userData.avatar : ('/' + store.currentUser.userData.avatar)}
                        fallback={userImageData}
                        preview={false}
                      />
                    }
                    size={56}
                  /> :
                  <Avatar
                    draggable={false}
                    src={
                      <Image
                        src={userImageData}
                        preview={false}
                        width={36}
                        height={36}
                      />
                    }
                    size={56}
                  />
              }
            </Button>
          </Dropdown>
        </div>
      </Header>

      <Modal
        title="用户信息"
        open={isUserModalOpen}
        okText="确定"
        cancelText="取消"
        maskClosable={false}
        destroyOnHidden
        closable={!isUserFormSaving}
        confirmLoading={isUserDataLoading || isUserFormSaving}
        afterOpenChange={getUserInfo}
        onOk={() => userForm.submit()}
        onCancel={() => {
          if (!isUserFormSaving) setIsUserModalOpen(false)
        }}
        style={{ minWidth: 320 }}
      >
        <Spin spinning={isUserDataLoading}>
          <Form
            form={userForm}
            name="userForm"
            autoComplete="off"
            disabled={isUserFormSaving}
            labelCol={{ span: 6 }}
            wrapperCol={{ span: 16 }}
            onFinish={updateUserInfo}
            onFinishFailed={() => messageApi.warning('数据校验错误')}
          >
            <Form.Item
              name="username"
              label="用户名"
              className="readonly"
            >
              <Input readOnly />
            </Form.Item>
            <Form.Item
              name="name"
              label="姓名"
            >
              <Input maxLength={32} />
            </Form.Item>
            <Form.Item
              name="company"
              label="公司"
            >
              <Input maxLength={32} />
            </Form.Item>
            <Form.Item
              name="department"
              label="部门"
            >
              <Input maxLength={32} />
            </Form.Item>
            <Form.Item
              name="title"
              label="职位"
            >
              <Input maxLength={32} />
            </Form.Item>
            <Form.Item
              name="email"
              label="邮箱"
              rules={[
                { pattern: patterns.emailPattern, message: '邮箱格式不正确' }
              ]}
            >
              <Input maxLength={64} />
            </Form.Item>
            <Form.Item
              name="mobile"
              label="手机"
              rules={[
                { required: true, message: '手机不能为空' },
                { pattern: patterns.mobilePattern, message: '手机格式不正确' }
              ]}
              tooltip={{ title: '11位数字手机号', icon: <InfoCircleOutlined /> }}
            >
              <Input maxLength={16} />
            </Form.Item>
            <Form.Item
              name="telephone"
              label="电话"
              rules={[
                { pattern: patterns.phonePattern, message: '电话格式不正确' }
              ]}
              tooltip={{ title: '格式：(2-3位区号)-(7-8位电话号码)-(1-4位分机号，可无分机号)', icon: <InfoCircleOutlined /> }}
            >
              <Input maxLength={32} />
            </Form.Item>
            <Form.Item
              name="superuser"
              valuePropName="checked"
              wrapperCol={{ sm: { offset: 6, span: 16 }, xs: { span: 24 } }}
              className="readonly"
            >
              <Checkbox disabled>
                <span style={{ color: 'rgba(0, 0, 0, 0.45)' }}>
                  管理员
                </span>
              </Checkbox>
            </Form.Item>
            <Form.Item
              name="typeName"
              label="类型"
              hidden={superuser}
              className="readonly"
            >
              <Input readOnly />
            </Form.Item>
            <Form.Item
              name="_avatar"
              label="头像"
            >
              <Upload
                accept=".jpg,.jpeg,.png"
                action="/api/upload"
                maxCount={1}
                name="file"
                headers={{'X-XSRF-TOKEN': xsrfToken}}
                fileList={fileList}
                onChange={({ file, fileList }) => {
                  setFileList(fileList);
                  if (fileList.length === 0) {
                    setAvatar(null);
                    setAvatarId(null);
                  } else if (fileList[0].status === 'done') {
                    const data = fileList[0].response.data;
                    fileList[0].uid = data.id;
                    fileList[0].name = data.filename;
                    fileList[0].status = 'done';
                    fileList[0].url = '/api/download/' + data.id;
                    setAvatar(null);
                    setAvatarId(data.id);
                    setFileList(fileList);
                  }
                }}
              >
                <Button icon={<UploadOutlined />}>
                  上传
                </Button>
              </Upload>
            </Form.Item>
            <Form.Item
              name="id"
              hidden={true}
            >
              <Input />
            </Form.Item>
          </Form>
        </Spin>
      </Modal>

      <Modal
        title="更改密码"
        open={isPasswordModalOpen || store.currentUser.needChangePassword}
        okText="确定"
        cancelText="取消"
        maskClosable={false}
        destroyOnHidden
        closable={!isPasswordFormSaving}
        confirmLoading={isPasswordFormSaving}
        afterOpenChange={fillPasswordForm}
        onOk={() => passwordForm.submit()}
        onCancel={() => {
          if (store.currentUser.needChangePassword) {
            messageApi.warning('必须更改密码')
            return;
          }
          if (!isPasswordFormSaving) {
            setIsPasswordModalOpen(false)
          }
        }}
        style={{ minWidth: 320 }}
        footer={(_, { OkBtn, CancelBtn }) => (
          <>
            <Popover
              content="密码长度为6-16位，必须包含数字，且必须包含字母或其它字符（!@_#$%^&*()-+=,.?）"
              title="密码规则"
              trigger="click"
            >
              <Button>
                <InfoCircleOutlined style={{ color: 'rgba(0, 0, 0, 0.45)' }} />
                密码规则
              </Button>
            </Popover>
            <CancelBtn />
            <OkBtn />
          </>
        )}
      >
        <Space
          direction="vertical"
          size={12}
          split
          style={{ width: '100%' }}
        >
          {
            store.currentUser.needChangePassword ?
              <Alert
                message="提示信息"
                description="您的密码已过期，或者管理员要求您更新密码。"
                type="warning"
                showIcon
              /> : null
          }
          <Form
            form={passwordForm}
            name="passwordForm"
            autoComplete="off"
            disabled={isPasswordFormSaving}
            labelCol={{ span: 6 }}
            wrapperCol={{ span: 16 }}
            onFinish={changePassword}
            onFinishFailed={() => messageApi.warning('数据校验错误')}
          >
            <Form.Item
              name="oldPassword"
              label="旧密码"
              rules={[{ required: true, message: '旧密码不能为空' }]}
            >
              <Input.Password maxLength={16} />
            </Form.Item>
            <Form.Item
              name="newPassword"
              label="新密码"
              rules={[
                { required: true, message: '新密码不能为空' },
                { pattern: patterns.passwordPattern, message: '密码不符合规则' }
              ]}
            >
              <Input.Password maxLength={16} />
            </Form.Item>
            <Form.Item
              name="confirmPassword"
              label="确定密码"
              rules={[
                { required: true, message: '确认密码不能为空' },
                ({ getFieldValue }) => ({
                  validator(_, value) {
                    if (!value || getFieldValue('newPassword') === value) {
                      return Promise.resolve();
                    }
                    return Promise.reject('确认密码与新密码不一致');
                  }
                })
              ]}
            >
              <Input.Password maxLength={16} />
            </Form.Item>
            <Form.Item label="有效期（月）">
              <Space size="middle">
                <Form.Item
                  name={['periodOfValidity', 'months']}
                  noStyle
                >
                  <InputNumber
                    max={12}
                    min={1}
                    precision={0}
                    step={1}
                    disabled={periodOfValidityDisabled}
                  />
                </Form.Item>
                <Form.Item
                  name={['periodOfValidity', 'neverExpire']}
                  valuePropName="checked"
                  noStyle
                >
                  <Checkbox onChange={updateValidityStatus}>
                    密码永不过期
                  </Checkbox>
                </Form.Item>
              </Space>
            </Form.Item>
          </Form>
        </Space>
      </Modal>

      <Modal
        title="审核意见"
        open={isOpinionModalOpen}
        maskClosable={false}
        destroyOnHidden
        afterOpenChange={showOpinions}
        onCancel={() => setIsOpinionModalOpen(false)}
        style={{ minWidth: 320 }}
        footer={null}
      >
        <Space
          direction="vertical"
          size={12}
          split
          style={{ width: '100%' }}
        >
          <Form
            form={opinionForm}
            name="opinionForm"
            autoComplete="off"
            labelCol={{ span: 6 }}
            wrapperCol={{ span: 16 }}
          >
            <Form.Item
              name="authorized"
              label="状态"
              valuePropName="checked"
              className="readonly"
            >
              <Switch disabled />
            </Form.Item>
            <Form.Item
              name="authorizedOpinions"
              label="意见"
              className="readonly"
            >
              <Input.TextArea
                autoSize={{ minRows: 3, maxRows: 5 }}
                readOnly
              />
            </Form.Item>
          </Form>
        </Space>
      </Modal>
    </>
  );
};

export default observer(HeaderLayout);
